package puppy.graph;

import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;

import org.apache.commons.collections15.Transformer;

import algorithms.Constants;

public class DeliciousNodeSimpleTransformer implements
Transformer<DeliciousNodeSimple, Double> {

	/**
	 * @param args
	 */

	Hashtable<String, Integer> totals_urls = null;
	Hashtable<String, Integer> totals_tags = null;
	Hashtable<String, Float> query = null;

	HashSet<String> n_grams = null;
	Hashtable<String, Float> n_grams_freq = null;

	// parameter used for smoothing of query probability
	double query_lamda = 0.9;
	double query_lamda_ngram = 0.9999;
	double query_total = 0.0;

	double n_gram_weight = 1;

	double top_n = 0.0;

	double ngram_extender_top_n1 = 3;

	/*
	 * 
	 * parameter to experiment
	 */

	CreateGraphOnlyTags graph = null;


	// calculate p(tag) or p(url)

	public DeliciousNodeSimpleTransformer(
			Hashtable<String, Float> query, 
			CreateGraphOnlyTags graph, String q_text, double n_gram_weight,
			int mimimum_length_ngram) {

	
		this.query = query;
	

		this.graph = graph;
		this.n_gram_weight = n_gram_weight;

		//this.n_grams = graph.query_phraser.getTagMatches(q_text,mimimum_length_ngram, false);
		//addNgramsTopNQueryTerms(query, mimimum_length_ngram, false);

		q_text = q_text.replace(" ","_");

		//	Hashtable<String, Float> query1 = generatePossibleTokensNGram(q_text);//borrar esto
		//n_grams_freq = assignNgramProb(n_grams, query);



		//Iterator<String> iter = n_grams.iterator();
		//while (iter.hasNext()) {
	//		iter.next();
			//System.out.println(iter.next());

		//}
		//	System.exit(0);

		// create extended query n-grams

	}


	public double calculateBackgroundProb(DeliciousNodeSimple node) {

		double total = Constants.TOTAL_NODE_MASS;
		
		double n = node.freq_adult+ 1;
	
		return (double) n / (double) total;

	}

	public double calculateKL(DeliciousNodeSimple node) {

		double fore = calculateForegroundProb(node);
		double back = calculateBackgroundProb(node);

		double kl = fore * Math.log(back) - fore * Math.log(fore);

		// double kl = Math.log(fore/back);
		// if(node.getName().equals(""))
		// System.out.println(node.getName()+"\tfore:"+ fore + "\tback: "+ back
		// + "\tscore:"+ kl );
		return kl;

	}

	public double calculateForegroundProb(DeliciousNodeSimple node) {
		double total = Constants.TOTAL_NODE_MASS;
		
		double n = node.freq;
		return (double) n / (double) total;

	}

	public double calculateNodePrior(DeliciousNodeSimple node) {

		double total = 0.0;


		double n = node.freq;
		if (node.name.equals("studios")) {
			// System.out.println("Prior:" + "\t"+ n + "\t" +total +"\t"+
			// agg.teens_mteens + "\t" + node.freq_type.get("teens-mteens") +
			// "\t"+ (double)n/(double)Constants.TOTAL_NODE_MASS + "\t"+
			// node.getId() );
			// printInfo(node.freq_type);
		}

		// double kl = calculateKL(node);

		// return (double)n/(double)Constants.TOTAL_NODE_MASS;
		return (double) n / (double) Constants.TOTAL_TAG_KIDS;
	}

	

	public double calculateQueryProb(DeliciousNodeSimple node) {

		Hashtable<String, Float> h = generatePossibleTokensNGram(node.name);
		Enumeration<String> keys = h.keys();
		float prob_sum=1;
		//	System.out.println("Query prob for :  " + node.getName());
		while(keys.hasMoreElements()){

			String k= keys.nextElement();

			if(query.containsKey(k)) {
				//System.out.println("matched:" + k + "\t" + node.getName() + "\t"+ query);

				float query_prob= query.get(k);
				prob_sum= (float) (prob_sum*(query_prob*(query_lamda_ngram) + calculateNodePrior(node)*(1-query_lamda_ngram)));
			}else{

				prob_sum= (float) (prob_sum*calculateNodePrior(node)*(1-query_lamda_ngram));
			}
		}


			return prob_sum;
		
	}

	/**
	 * Returns true if tag is in target
	 * 
	 * e.g star_wars <==> star
	 * 
	 * star_wars_lego <==> lego
	 * 
	 * @param target
	 * @param tag
	 * @return
	 */
	public boolean isInTargetAsToken(String target, String tag) {

		if (target.endsWith("_" + tag))
			return true;

		if (target.startsWith(tag + "_"))
			return true;

		if (target.contains("_" + tag + "_"))
			return true;

		if (tag.endsWith("_" + target))
			return true;

		if (tag.startsWith(target + "_"))
			return true;

		if (tag.contains("_" + target + "_"))
			return true;

		return false;
	}

	public Hashtable<String, Float> generatePossibleTokensNGram(String query_text) {
		Hashtable<String, Float> h = new Hashtable<String, Float>();

		String ngram = query_text.replace(" ", "_");
		String t[] = ngram.split("_");

		if (graph.tag_names.containsKey(ngram)) {

			float prior = (float) calculateNodePrior(graph.tag_names.get(ngram));
			h.put(ngram, (float) (prior * (1f - query_lamda_ngram)));

		}

		for (int i = 0; i < t.length; i++) {

			if (graph.tag_names.containsKey(t[i])) {
				float prior = (float) calculateNodePrior(graph.tag_names
						.get(t[i]));
				h.put(t[i], (float) (prior * (1f - query_lamda_ngram)));
			}

			if (i + 1 < t.length) {

				String m = t[i] + "_" + t[i + 1];
				if (graph.tag_names.containsKey(m)) {

					float prior = (float) calculateNodePrior(graph.tag_names
							.get(m));
					h.put(m, (float) (prior * (1f - query_lamda_ngram)));
				}

			}

			if (i + 2 < t.length) {

				String m = t[i] + "_" + t[i + 1] + "_" + t[i + 2];
				if (graph.tag_names.containsKey(m)) {

					float prior = (float) calculateNodePrior(graph.tag_names
							.get(m));
					h.put(m, (float) (prior * (1f - query_lamda_ngram)));
				}

			}

		}

		return h;
	}

	

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String s = "star_wars_lego";
		String t = "wars1";

	}

	@Override
	public Double transform(DeliciousNodeSimple input) {
		// TODO Auto-generated method stub

		double t = calculateQueryProb(input);

		return t;
	}

	public void clean() {

		query.clear();
	//	n_grams.clear();
	//	n_grams_freq.clear();
		query = null;
		n_grams = null;
		n_grams_freq = null;

	
		totals_urls = null;
		totals_tags = null;
	}

}